package comp9417;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * Created by huy on 3/06/14.
 */
public class ARFFLoader implements Loader {

    private final Scanner scanner;
    private State state = State.LOAD_ATTRIBUTE;

    public ARFFLoader(Scanner scanner) {
        this.scanner = scanner;
    }

    @Override
    public Dataset load() {
        Dataset dataset = new Dataset(getAttributes());
        String line = nextLine();
        while (state == State.LOAD_DATA) {
            DataPoint dataPoint = new DataPoint(dataset.getNumberOfAttributes());
            String[] points = line.split(",");
            for (int index = 0; index < points.length; index++) {
                Attribute attribute = dataset.getAttributes()[index];
                attribute.type.addValueToDatapoint(attribute, dataPoint, index, points);
            }
            dataset.addPoint(dataPoint);
            line = nextLine();
        }
        return dataset;
    }

    private Attribute[] getAttributes() {
        List<Attribute> attributes = new ArrayList<Attribute>();
        String line = nextLine();
        while (state == State.LOAD_ATTRIBUTE) {
            String[] fields = line.split(" ");
            Attribute attribute;
            if (fields[2].startsWith("{")) {
                attribute = new Attribute(fields[1], AttributeType.CATEGORICAL);
                String[] categories = line.substring(line.indexOf("{") + 1, line.indexOf("}")).split(",");
                for (String category : categories) {
                    attribute.categories.put(category.trim(), 0);
                }
            } else {
                attribute = new Attribute(fields[1], AttributeType.CONTINUOUS);
            }
            attributes.add(attribute);
            line = nextLine();
        }
        return attributes.toArray(new Attribute[attributes.size()]);
    }

    private String nextLine() {
        String line = "";
        if (scanner.hasNext()) {
            while (scanner.hasNext() && ("".equals(line) || line.startsWith("%"))) {
                line = scanner.nextLine();
            }
            if (!scanner.hasNext()) state = State.END;
            if (line.startsWith("@relation")) line = nextLine();
            if (line.startsWith("@attribute")) state = State.LOAD_ATTRIBUTE;
            if (line.startsWith("@data")) state = State.LOAD_DATA;
        } else {
            state = State.END;
        }
        return line;
    }
}
